
#include "klog.h"
#include "knxcontroller.h"
#include "knxenvagent.h"
#include "frame_interface.h"


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/// \brief KNXController::KNXController
/// \param parent

KNXController::KNXController(QObject *parent) :
    QThread(parent)
{
    self = QString("KNXController: %1l").arg((qlonglong)this);
    _knx = NULL;
    busMonitor_data_len = 0;
    //_udpSocket.bind(QHostAddress::Any, 1027);
//    _udpSocket.bind(QHostAddress("192.168.0.104"), 1027);
//    connect(&_udpSocket,SIGNAL(readyRead()),this,SLOT(readUdpData()));

}

KNXController::~KNXController()
{
    if(this->isRunning())
        this->quit();

    if(_knx)
    {
        _knx->deleteLater();
        _knx = NULL;
    }
}

void KNXController::readUdpData()
{
    char buff[128] = {0};
    QByteArray cmdBytes;

    if (_udpSocket.bytesAvailable() < (int)sizeof(quint16))
        return;

    int len = _udpSocket.readDatagram(buff,128);

    qDebug()<<"KNXController read udp data: " << len << buff;
}

bool KNXController::setConenctType(KNX_CONNECT_TYPE type, QString serverIp,QString localIpAddr)
{
//    if(!KnxEnvAgent::getFreePort(&control_port,&data_port))
//        return false;

    this->type = type;
    this->serverIp = serverIp;
    this->localIpAddr = localIpAddr;

    //qDebug(itself + "New object, control_port %u data_port %u server_port %u , serverIp %s localIpAddr %s \n",control_port,data_port,serverPort,serverIp,localIpAddr);
    KDEBUG << " type:" << type << " ip:" << serverIp << " use local ip:" << localIpAddr;

    return true;
}


void KNXController::doWork()
{
    //setPriority(priority);
    if(!serverIp.isEmpty())
    {
        mutex.lock();
        this->start();
        threadWait.wait(&mutex);
        mutex.unlock();
    }
    else
    {
        KDEBUG << "KNX not init,please set the KNX Engine first!";
    }
}

void KNXController::run()
{
    _knx = new KNXEngine();
    //_knx->moveToThread(this);
    _knx->initNetWorkEnv(serverIp,localIpAddr,control_port,data_port,type);
    _knx->busMonitor_data_len = this->busMonitor_data_len;

    if(!_knx->readyWork())
    {
        KDEBUG << "start knx engine fail, thread exit !" ;
        threadWait.wakeAll();
        return ;
    }

    // this -> knx slots
    connect(this,SIGNAL(KNXEngineReadValue(QByteArray ,int)),
            _knx,SLOT(getValue(QByteArray,int)),Qt::QueuedConnection);
    connect(this,SIGNAL(KNXEngineWriteValue(QByteArray,int ,QByteArray )),
            _knx,SLOT(setValue(QByteArray ,int ,QByteArray)),Qt::QueuedConnection);

    connect(this,SIGNAL(KNXRegistObject(void *,void *)),
            _knx,SLOT(registeObject(void *,void *)),Qt::QueuedConnection);

    connect(this,SIGNAL(KNXUnRegistObject(void *,void *)),
            _knx,SLOT(unRegisterObject(void *,void *)),Qt::QueuedConnection);

    connect(this,SIGNAL(KNXObjUpdate()),
            _knx,SLOT(updateObjs()),Qt::QueuedConnection);

    // knx->this  signals
    connect(_knx,SIGNAL(engineValueNotify(void *,QByteArray,void *)),
            this,SIGNAL(CBDeviceValueUpdate(void *,QByteArray,void *)),Qt::QueuedConnection);
    connect(_knx,SIGNAL(engineErrorNotify(QString ,int )),
            this,SIGNAL(CBServerErrorNotify(QString,int)),Qt::QueuedConnection);
    connect(_knx,SIGNAL(routingMonitorNotify(QString,QByteArray)),
            this,SIGNAL(CBRoutingMonitorNotify(QString,QByteArray)),Qt::QueuedConnection);

    _knx->startWork();
    threadWait.wakeAll();

    KDEBUG << ":KNX engine start success.";

    this->exec();

    _knx->stopWork();
    delete(_knx);
    _knx=NULL;

    KDEBUG << ":KNX engine exit.";

}

void KNXController::doStop(){
    this->exit();
    this->wait();
}

void KNXController::registeEibObject(void *devObj, void *userdata)
{
    emit KNXRegistObject(devObj,userdata);
}

void KNXController::unRegisterEibObject(void *devObj, void *userdata){
    emit KNXUnRegistObject(devObj,userdata);
}

void KNXController::writeValue(QByteArray address, int type, QByteArray value)
{
    int times = 2;
    while(this->isRunning() && times -- >0)
    {
        if(_knx->isConnectToServer())
        {
            emit KNXEngineWriteValue(address,type,value);
            return;
        }
        else
        {
            sleep(1);
        }
    }

    KDEBUG << "Thread has trying to conenct KNX server,write device fail!" << address;
}

void KNXController::readValue(QByteArray address,int type)
{
    emit KNXEngineReadValue(address,type);
}

QString KNXController::serverIpAddress(){
    if(_knx)
        return _knx->ipV4Server.toString();
    else
        return QString();
}


